Engineering Logical Inflammation Sensing Circuit for Gut Modulation

Longitudinal Activation, for RBS Figure 2CD

Liana Merk

In [1]:
import numpy as np
import pandas as pd

import holoviews as hv
hv.extension('bokeh')

import bokeh
from bokeh.models import PrintfTickFormatter

import warnings
warnings.filterwarnings('ignore')

bokeh.io.output_notebook()
Loading BokehJS ...
In [2]:
df = pd.read_excel("./data/20191117_highttr_curves.xlsm", na_values = '*')

Tidy the Data

In [3]:
# Parse GFP Columns
df_gfp = df.iloc[346:634, 1:]
df_gfp.columns = df.iloc[345, 1:].values
df_gfp.reset_index(inplace=True, drop=True)
df_gfp.drop(df_gfp.columns[1], axis =1, inplace=True)
df_gfp = df_gfp.melt(value_name='GFP', id_vars='Time')
df_gfp['Time'] = df_gfp['Time'].apply(lambda x: x.hour *60 + x.minute)
In [4]:
# And OD columns
df_OD = df.iloc[53:341, 1:]
df_OD.columns = df.iloc[52, 1:].values
df_OD.reset_index(inplace=True, drop=True)
df_OD.drop(df_OD.columns[1], axis =1, inplace=True)
df_OD = df_OD.melt(value_name='OD', id_vars='Time')
df_OD['Time'] = df_OD['Time'].apply(lambda x: x.hour + x.minute/60)
In [5]:
# Put GFP onto OD dataframe
df_OD['GFP'] = df_gfp['GFP']
In [6]:
# Samples are column-based, so just extract column
df_OD['Sample'] = df_gfp['variable'].apply(lambda x: x[1:])
In [7]:
# Engineered strains only in these columns
df_OD_filt = df_OD.loc[df_OD['Sample'].isin(['1', '3', '5', '7', '9', '11', '12'])]
In [8]:
# Find which samples are in which columns
di = {'1': "LM13",
    '3': 'LM14',
    '5': 'LM15',
    '7': 'LM17',
    '9': 'LM18',
    '11': 'LM19',
    '12': 'CSH50'}
df_OD_filt.replace({"Sample": di}, inplace=True)
In [9]:
# Row-based tetrathionate concentrations
df_OD_filt['TTR_Concentration_mM'] = df_OD_filt['variable'].apply(lambda x: x[0:1])
conc = {'A': '0',
    'B': '0.1',
    'C': '0.25',
    'D': '0.5',
    'E': '0.75',
    'F': '1',
    'G': '5',
    'H': '10'}
df_OD_filt.replace({'TTR_Concentration_mM': conc}, inplace=True)
df_OD_filt.head()
Out[9]:
Time variable OD GFP Sample TTR_Concentration_mM
0 0.033333 A1 0.227 2739 LM13 0
1 0.116667 A1 0.241 2688 LM13 0
2 0.200000 A1 0.262 2653 LM13 0
3 0.283333 A1 0.297 2602 LM13 0
4 0.366667 A1 0.32 2536 LM13 0
In [10]:
df_OD_filt = df_OD_filt.rename(columns={"Time": "Time_hr", "variable": "well"})
df_OD_filt['GFP/OD'] = df_OD_filt['GFP'] / df_OD_filt['OD']
In [11]:
df_OD_filt['Sample'].unique()
Out[11]:
array(['LM13', 'LM14', 'LM15', 'LM17', 'LM18', 'LM19', 'CSH50'],
      dtype=object)
In [12]:
titles = ['Very Low (LM15) Response', 'Low (LM14) Response', 'Medium (LM18) Response', 'High (LM19) Response']
In [13]:
color = list(bokeh.palettes.Viridis10[1:-1])
color.reverse()

Plot Experimental

In [14]:
# Convert to AU
df_OD_filt['GFP/OD_scaled'] = df_OD_filt['GFP/OD'] / 10e4
df_OD_filt['TTR_Concentration_mM'] = pd.to_numeric(df_OD_filt['TTR_Concentration_mM'])
In [15]:
hv.extension("bokeh")
plot_list = []

for i, sample in enumerate(['LM15', 'LM14', 'LM18', 'LM19']):
    p = hv.render(hv.Curve(
        # Change df to 
        data=df_OD_filt.loc[df_OD_filt["Sample"] == sample],
        kdims=[("Time_hr", "Time (hr)"), ("GFP/OD_scaled", "GFP/OD₇₀₀ (AU)")],
        vdims=[("TTR_Concentration_mM", "Tetrathionate (mM)")],
    )
    .groupby("TTR_Concentration_mM")
    .opts(
        color=hv.Cycle(color),
        frame_height=2500,
        frame_width=3000,
        # Only show legend on first plot
        show_legend=i == 0,
        title = f'{titles[i]}',
        line_width=30,
        fontscale = 20,
        ylim = (-0.1, 2.5),
        xlim = (-1, 23),
        show_grid=True,
    )
    .overlay()
    .opts(
        legend_position="left",
        # Display legend horizontally
        legend_cols=True,
        # Format legend to fit
        
    ))
    
    p.legend.label_text_font_size="100pt" 
    p.legend.title_text_font_size="130pt"
    p.legend.title_text_font_style="normal"

    p.legend.glyph_width=100
    p.legend.glyph_height = 200
    p.legend.spacing = 100
    p.legend.label_standoff = 40


    
    p.xaxis.axis_label_text_font_style = 'normal'
    p.yaxis.axis_label_text_font_style = 'normal'

    p.title.text_font_size = '160pt'
    p.xaxis.major_tick_line_width = 10
    p.yaxis.major_tick_line_width = 10
    
    p.xaxis.minor_tick_line_width = 10
    p.yaxis.minor_tick_line_width = 10
    p.axis.minor_tick_out = 20
    p.axis.minor_tick_out = 20
    
    p.axis.major_tick_out = 40
    p.axis.major_tick_out = 40
    p.yaxis.axis_label_standoff = 50
    p.xaxis.axis_label_standoff = 50
    
    p.xaxis.axis_line_width = 8
    p.yaxis.axis_line_width = 8

    p.yaxis.major_label_standoff = 30
    p.xaxis.major_label_standoff = 30
    
    p.xgrid.visible =True
    p.ygrid.visible =True
    p.ygrid.grid_line_width = 10
    p.xgrid.grid_line_width = 10
    p.toolbar_location=None

    plot_list.append(p)

bokeh.io.show(bokeh.layouts.gridplot([plot_list]))
In [16]:
bokeh.io.export_png(bokeh.layouts.gridplot([plot_list]), filename="./figures/fig2/fig2d.png")
Out[16]:
'/Users/lianamerk/CALTECH/3.3/liana_merk_paper/figures/fig2/fig2d.png'

Plot Simulation data

In [17]:
all_sims = pd.read_csv('./data/all_sims.csv')
all_sims_melted = all_sims.melt(id_vars = 'Time (hr)', var_name = 'sample1', value_name = 'GFP')
all_sims_melted[['title', 'conc']] = all_sims_melted['sample1'].str.split('_', expand=True)
all_sims_melted['conc'] = pd.to_numeric(all_sims_melted['conc'])
all_sims_melted['Time (hr)'] = all_sims_melted['Time (hr)'] / 60
In [18]:
plot_list = []

for i, title in enumerate(all_sims_melted.title.unique()):
    p = hv.render(hv.Curve(
        # Change df to 
        data=all_sims_melted.loc[all_sims_melted.title == title],
        kdims=[("Time (hr)"), ("GFP", "GFP (AU)")],
        vdims=[("conc", "[TTR] (mM)")],
    )
    .groupby("conc")
    .opts(
        color=hv.Cycle(color),
        frame_height=2500,
        frame_width=3000,
        # Only show legend on first plot
        show_legend=i == 0,
        title = f'{title}',
        line_width=30,
        fontscale = 20,
        ylim = (-0.1, 2.5),
        show_grid=True,
        xlim = (-1, 23),
    )
    .overlay()
    .opts(
        show_legend=False,
    ))

    
    p.xaxis.axis_label_text_font_style = 'normal'
    p.yaxis.axis_label_text_font_style = 'normal'

    p.title.text_font_size = '160pt'
    p.xaxis.major_tick_line_width = 10
    p.yaxis.major_tick_line_width = 10
    
    p.xaxis.minor_tick_line_width = 10
    p.yaxis.minor_tick_line_width = 10
    p.axis.minor_tick_out = 20
    p.axis.minor_tick_out = 20
    
    p.axis.major_tick_out = 40
    p.axis.major_tick_out = 40
    p.yaxis.axis_label_standoff = 50
    p.xaxis.axis_label_standoff = 50
    
    p.xaxis.axis_line_width = 8
    p.yaxis.axis_line_width = 8

    p.yaxis.major_label_standoff = 30
    p.xaxis.major_label_standoff = 30
    
    p.xgrid.visible =True
    p.ygrid.visible =True
    p.ygrid.grid_line_width = 10
    p.xgrid.grid_line_width = 10
    p.toolbar_location=None

    plot_list.append(p)

bokeh.io.show(bokeh.layouts.gridplot([plot_list]))
In [19]:
bokeh.io.export_png(bokeh.layouts.gridplot([plot_list]), filename="./figures/fig2/fig2c.png")
Out[19]:
'/Users/lianamerk/CALTECH/3.3/liana_merk_paper/figures/fig2/fig2c.png'

Computing Environment

In [20]:
%load_ext watermark
%watermark -v -p numpy,scipy,pandas,bokeh,holoviews,jupyterlab
CPython 3.7.6
IPython 7.13.0

numpy 1.18.1
scipy 1.4.1
pandas 1.0.3
bokeh 2.0.1
holoviews 1.13.2
jupyterlab 2.1.0